package tmt.usercenter.web.service;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tmt.usercenter.web.Application;
import tmt.usercenter.web.configure.security.bean.IgniteTokenStore;
import tmt.usercenter.web.configure.security.bean.TmtServerSessionRegistry;
import tmt.usercenter.web.domain.LoginHistory;
import tmt.usercenter.web.domain.TmtUser;
import tmt.usercenter.web.repository.ILoginHistoryRepo;

import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class LoginHistoryService extends TmtBaseService<LoginHistory, Long> {

    public static final boolean SINGLE_SIGN_OUT = true;

    @Getter
    private ILoginHistoryRepo iLoginHistoryRepo;

    @Autowired
    private TmtServerSessionRegistry sessionRegistry;

    @Autowired
    private ClientSystemService clientSystemService;

    @Autowired
    private TmtUserService userService;

    @Autowired
    private TokenStore tokenStore;


    @Autowired
    public LoginHistoryService(ILoginHistoryRepo iLoginHistoryRepo) {
        super(iLoginHistoryRepo, new ArrayList<>());
        this.iLoginHistoryRepo = iLoginHistoryRepo;
    }

    /**
     * 在ClientId系统上的UserId用户登出系统了
     *
     * @param userId
     * @param clientId
     */
    @Async
    public void userLogout(Long userId, String clientId) {
        //清除Session
        sessionRegistry.invalidateSession(userId, SINGLE_SIGN_OUT ? null : clientId);

        //单点登出，回写所有登录记录的登出时间。
        List<LoginHistory> list = SINGLE_SIGN_OUT ?
                iLoginHistoryRepo.findLastHistories(userId) :
                iLoginHistoryRepo.findLastHistories(userId, clientId);
        list.forEach(x -> x.setLogoutTime(new Date()));
        iLoginHistoryRepo.save(list);

        userService.updateOnline(userId, false);

        //从令牌仓库中删除作废的令牌。
        TmtUser user = userService.findById(userId);
        if (user != null) {
            Collection<OAuth2AccessToken> tokenList = tokenStore.findTokensByClientIdAndUserName(clientId, user.getUsername());
            tokenList.forEach(x -> tokenStore.removeAccessToken(x));
        }

        list.parallelStream()
                .filter(x -> !Objects.equals(x.getOriginSystem().getClientId(), clientId)
                        && !Objects.equals(x.getOriginSystem().getClientId(), Application.SYSTEM_ID))
                .forEach(x -> {
                    try {
                        //通知该用户登录的其他系统，告知这些系统该用户已经登出了。
                        clientSystemService.sendLogoutNotifyToClient(clientId, userId);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                });

    }

}
